package com.ksyun.ks3.services;

import android.content.Context;
import android.text.TextUtils;
import android.util.Log;

import com.ksyun.ks3.auth.AuthEvent;
import com.ksyun.ks3.exception.Ks3ClientException;
import com.ksyun.ks3.model.HttpMethod;
import com.ksyun.ks3.model.acl.Authorization;
import com.ksyun.ks3.services.handler.AsyncHttpResponseHandler;
import com.ksyun.ks3.services.request.GetObjectRequest;
import com.ksyun.ks3.services.request.Ks3HttpRequest;
import com.ksyun.ks3.util.Constants;
import com.ksyun.ks3.util.ModelUtil;

import java.io.IOException;
import java.io.InputStream;

import okhttp3.Call;
import okhttp3.Headers;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class Ks3HttpExecutor {

    private OkHttpClient client;

    public void invoke(Authorization auth, final Ks3HttpRequest request,
                       final AsyncHttpResponseHandler resultHandler,
                       Ks3ClientConfiguration clientConfiguration, final Context context,
                       String endpoint, AuthListener authListener, Boolean isUseAsyncMode) {
        if (TextUtils.isEmpty(endpoint)) {
            Log.e(Constants.LOG_TAG, "The endpoint is empty,do you call setEndpoint() after you create Ks3Client?");
            return;
        }

        /* Configure AsyncHttpClient */
        if (clientConfiguration != null) {
            client = OkHttpClientFactory.getInstance(clientConfiguration);
        } else {
            client = OkHttpClientFactory.getInstance();
        }

        request.setAuthorization(auth);
        //设置host
        if (request.getBucketname() == null || clientConfiguration.isPathStyleAccess() || clientConfiguration.getDomainMode()) {
            request.setEndpoint(endpoint);
        } else {
            request.setEndpoint(request.getBucketname() + "." + endpoint);
        }

        request.setUseAsyncMode(isUseAsyncMode);
        // Token形式
        if (authListener != null) {
            request.setAuthListener(authListener);
            // 开线程执行 initRequestParams
            setUpRequestInBackground(request, new Ks3AuthHandler() {

                @Override
                public void onSuccess(AuthEvent event) {
                    doRequest(request, context, resultHandler);
                }

                @Override
                public void onFailure(AuthEvent event) {
                    resultHandler.onFailure(request, new Ks3ClientException(event.getContent()), null);
                }
            }, resultHandler);
        }
        // AK&SK形式
        else {
            try {
                request.initRequestParams(null, resultHandler);
            } catch (Ks3ClientException e) {
                resultHandler.onFailure(request, e, null);
                return;
            }
            doRequest(request, context, resultHandler);
        }
    }

    protected void doRequest(Ks3HttpRequest request, Context context,
                             AsyncHttpResponseHandler resultHandler) {
        resultHandler.setRequest(request);
        Request.Builder builder = new Request.Builder()
                .url(request.getUrl())
                .tag(context.getClass())
                .headers(ModelUtil.convertHeaderArray(request.getHeader()));
        builder.addHeader("Connection", "close");

        Request okHttpRequest = null;
        // For test
        LogShow(request);
        Log.d(Constants.LOG_TAG, "request url = " + request.getUrl());

        InputStream inputStream = null;
        String stringBody = null;
        switch (request.getHttpMethod()) {
            case POST:
            case PUT:
                // file inputStream
                if (request.getInputStreamBody() != null) {
                    inputStream = request.getInputStreamBody();

                    RequestBody body = NetworkProgressHelper.addProgressRequestBody(
                            inputStream,
                            request.getContentLength(),
                            request.getContentType(),
                            resultHandler);

                    builder = builder.method(request.getHttpMethod().toString(), body);
                } else if (request.getRequestBody() != null) {
                    builder = builder.method(request.getHttpMethod().toString(), request.getRequestBody());
                } else {
                    builder = builder.method(request.getHttpMethod().toString(), RequestBody.create(null, new byte[0]));
                }
                break;
            case GET:
                builder = builder.get();
                break;
            case DELETE:
                builder = builder.delete();
                break;
            case HEAD:
                builder = builder.head();
                break;
            default:
                Log.e(Constants.LOG_TAG, "unsupport http method ! ");
                break;
        }

        builder.addHeader("Content-Length", request.getContentLength() + "");

        okHttpRequest = builder.build();

        //	判断是否是getObject操作 如果是则添加进度监听器
        if (request instanceof GetObjectRequest && !TextUtils.isEmpty(request.getObjectkey())) {
            client = NetworkProgressHelper.addProgressResponseListener(this.client, resultHandler);
        }

        Call call = client.newCall(okHttpRequest);
        request.setRequestCall(call);
        if (request.isUseAsyncMode()) {
            call.enqueue(resultHandler);
        } else {
            try {
                Response response = call.execute();
                Log.d("Ks3HttpExecutor", response.toString());
                resultHandler.onResponse(call, response);
            } catch (IOException e) {
                resultHandler.onFailure(call, e);
            }
        }

    }

    private void setUpRequestInBackground(final Ks3HttpRequest request,
                                          final Ks3AuthHandler ks3AuthHandler,
                                          final AsyncHttpResponseHandler resultHandler) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    request.initRequestParams(ks3AuthHandler, resultHandler);
                } catch (Ks3ClientException e) {
                    ks3AuthHandler.isNeedCalculateAuth = false;
                    resultHandler.onFailure(request, e, null);
                }
            }
        }).start();
    }

    private void LogShow(Ks3HttpRequest request) {
        String url = request.getAsyncHttpRequestParam().getUrl();
        Headers headers = request.getAsyncHttpRequestParam().getHeaders();
        HttpMethod httpMethod = request.getHttpMethod();

        StringBuffer sb = new StringBuffer();
        sb.append("**url** " + url).append("\n");
        sb.append("**method** " + httpMethod.toString() + "\n");
        sb.append("**heads** ").append("\n");
        for (int i = 0; i < headers.size(); i++) {
            sb.append(headers.name(i)).append("=>").append(headers.value(i)).append("\n");
        }
        Log.d(Constants.LOG_TAG, sb.toString());
    }

}
